﻿// Decompiled with JetBrains decompiler
// Type: UnityEngine.EnumDataUtility
// Assembly: UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E6AE6B5A-2752-4B07-9528-C8B77C62CE79
// Assembly location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
// XML documentation location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.xml

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

#nullable disable
namespace UnityEngine
{
  internal static class EnumDataUtility
  {
    private static readonly Dictionary<System.Type, EnumData> s_NonObsoleteEnumData = new Dictionary<System.Type, EnumData>();
    private static readonly Dictionary<System.Type, EnumData> s_EnumData = new Dictionary<System.Type, EnumData>();

    internal static EnumData GetCachedEnumData(
      System.Type enumType,
      bool excludeObsolete = true,
      Func<string, string> nicifyName = null)
    {
      EnumData cachedEnumData1;
      if (excludeObsolete && EnumDataUtility.s_NonObsoleteEnumData.TryGetValue(enumType, out cachedEnumData1) || !excludeObsolete && EnumDataUtility.s_EnumData.TryGetValue(enumType, out cachedEnumData1))
        return cachedEnumData1;
      EnumData cachedEnumData2 = new EnumData()
      {
        underlyingType = Enum.GetUnderlyingType(enumType)
      };
      cachedEnumData2.unsigned = cachedEnumData2.underlyingType == typeof (byte) || cachedEnumData2.underlyingType == typeof (ushort) || cachedEnumData2.underlyingType == typeof (uint) || cachedEnumData2.underlyingType == typeof (ulong);
      FieldInfo[] fields = enumType.GetFields(BindingFlags.Static | BindingFlags.Public);
      List<FieldInfo> source = new List<FieldInfo>();
      int length1 = fields.Length;
      for (int index = 0; index < length1; ++index)
      {
        if (EnumDataUtility.CheckObsoleteAddition(fields[index], excludeObsolete))
          source.Add(fields[index]);
      }
      if (!source.Any<FieldInfo>())
      {
        string[] strArray = new string[1]{ "" };
        Enum[] enumArray = new Enum[0];
        int[] numArray = new int[1];
        cachedEnumData2.values = enumArray;
        cachedEnumData2.flagValues = numArray;
        cachedEnumData2.displayNames = strArray;
        cachedEnumData2.names = strArray;
        cachedEnumData2.tooltip = strArray;
        cachedEnumData2.flags = true;
        cachedEnumData2.serializable = true;
        return cachedEnumData2;
      }
      try
      {
        if (!string.IsNullOrEmpty(source.First<FieldInfo>().Module.Assembly.Location))
          source = source.OrderBy<FieldInfo, int>((Func<FieldInfo, int>) (f => f.MetadataToken)).ToList<FieldInfo>();
      }
      catch
      {
      }
      cachedEnumData2.displayNames = source.Select<FieldInfo, string>((Func<FieldInfo, string>) (f => EnumDataUtility.EnumNameFromEnumField(f, nicifyName))).ToArray<string>();
      if (((IEnumerable<string>) cachedEnumData2.displayNames).Distinct<string>().Count<string>() != cachedEnumData2.displayNames.Length)
        Debug.LogWarning((object) ("Enum " + enumType.Name + " has multiple entries with the same display name, this prevents selection in EnumPopup."));
      cachedEnumData2.tooltip = source.Select<FieldInfo, string>((Func<FieldInfo, string>) (f => EnumDataUtility.EnumTooltipFromEnumField(f))).ToArray<string>();
      cachedEnumData2.values = source.Select<FieldInfo, Enum>((Func<FieldInfo, Enum>) (f => (Enum) f.GetValue((object) null))).ToArray<Enum>();
      cachedEnumData2.flagValues = cachedEnumData2.unsigned ? ((IEnumerable<Enum>) cachedEnumData2.values).Select<Enum, int>((Func<Enum, int>) (v => (int) Convert.ToUInt64((object) v))).ToArray<int>() : ((IEnumerable<Enum>) cachedEnumData2.values).Select<Enum, int>((Func<Enum, int>) (v => (int) Convert.ToInt64((object) v))).ToArray<int>();
      cachedEnumData2.names = new string[cachedEnumData2.values.Length];
      for (int index = 0; index < cachedEnumData2.values.Length; ++index)
        cachedEnumData2.names[index] = cachedEnumData2.values[index].ToString();
      if (cachedEnumData2.underlyingType == typeof (ushort))
      {
        int index = 0;
        for (int length2 = cachedEnumData2.flagValues.Length; index < length2; ++index)
        {
          if (cachedEnumData2.flagValues[index] == (int) ushort.MaxValue)
            cachedEnumData2.flagValues[index] = -1;
        }
      }
      else if (cachedEnumData2.underlyingType == typeof (byte))
      {
        int index = 0;
        for (int length3 = cachedEnumData2.flagValues.Length; index < length3; ++index)
        {
          if (cachedEnumData2.flagValues[index] == (int) byte.MaxValue)
            cachedEnumData2.flagValues[index] = -1;
        }
      }
      cachedEnumData2.flags = enumType.IsDefined(typeof (FlagsAttribute), false);
      cachedEnumData2.serializable = cachedEnumData2.underlyingType != typeof (long) && cachedEnumData2.underlyingType != typeof (ulong);
      if (excludeObsolete)
        EnumDataUtility.s_NonObsoleteEnumData[enumType] = cachedEnumData2;
      else
        EnumDataUtility.s_EnumData[enumType] = cachedEnumData2;
      return cachedEnumData2;
    }

    internal static int EnumFlagsToInt(EnumData enumData, Enum enumValue)
    {
      if (!enumData.unsigned)
        return Convert.ToInt32((object) enumValue);
      if (enumData.underlyingType == typeof (uint))
        return (int) Convert.ToUInt32((object) enumValue);
      if (enumData.underlyingType == typeof (ushort))
      {
        ushort uint16 = Convert.ToUInt16((object) enumValue);
        return uint16 == ushort.MaxValue ? -1 : (int) uint16;
      }
      byte num = Convert.ToByte((object) enumValue);
      return num == byte.MaxValue ? -1 : (int) num;
    }

    internal static Enum IntToEnumFlags(System.Type enumType, int value)
    {
      EnumData cachedEnumData = EnumDataUtility.GetCachedEnumData(enumType);
      if (!cachedEnumData.unsigned)
        return Enum.Parse(enumType, value.ToString()) as Enum;
      if (cachedEnumData.underlyingType == typeof (uint))
      {
        uint num = (uint) value;
        return Enum.Parse(enumType, num.ToString()) as Enum;
      }
      if (cachedEnumData.underlyingType == typeof (ushort))
      {
        ushort num = (ushort) value;
        return Enum.Parse(enumType, num.ToString()) as Enum;
      }
      byte num1 = (byte) value;
      return Enum.Parse(enumType, num1.ToString()) as Enum;
    }

    private static bool CheckObsoleteAddition(FieldInfo field, bool excludeObsolete)
    {
      object[] customAttributes = field.GetCustomAttributes(typeof (ObsoleteAttribute), false);
      if (customAttributes.Length == 0)
        return true;
      return !excludeObsolete && !((ObsoleteAttribute) ((IEnumerable<object>) customAttributes).First<object>()).IsError;
    }

    private static string EnumTooltipFromEnumField(FieldInfo field)
    {
      object[] customAttributes = field.GetCustomAttributes(typeof (TooltipAttribute), false);
      return customAttributes.Length != 0 ? ((TooltipAttribute) ((IEnumerable<object>) customAttributes).First<object>()).tooltip : string.Empty;
    }

    private static string EnumNameFromEnumField(FieldInfo field, Func<string, string> nicifyName)
    {
      object[] customAttributes = field.GetCustomAttributes(typeof (InspectorNameAttribute), false);
      if (customAttributes.Length != 0)
        return ((InspectorNameAttribute) ((IEnumerable<object>) customAttributes).First<object>()).displayName;
      return field.IsDefined(typeof (ObsoleteAttribute), false) ? NicifyName() + " (Obsolete)" : NicifyName();

      string NicifyName() => nicifyName == null ? field.Name : nicifyName(field.Name);
    }
  }
}
